public class test1 {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("========== notify() 及其相关方法演示 ==========\n");

        // 示例1：基础的 wait/notify 演示
        System.out.println("【示例1】基础的 wait/notify 演示");
        example1_BasicWaitNotify();

        System.out.println("\n" + "=".repeat(50) + "\n");

        // 示例2：notifyAll() 演示
        System.out.println("【示例2】notifyAll() 演示（唤醒所有等待线程）");
        example2_NotifyAll();

        System.out.println("\n" + "=".repeat(50) + "\n");

        // 示例3：wait(timeout) 演示
        System.out.println("【示例3】wait(timeout) 演示（带超时的等待）");
        example3_WaitWithTimeout();
    }

    /**
     * 示例1：基础的 wait/notify 演示
     * 演示生产者-消费者模式
     */
    static void example1_BasicWaitNotify() throws InterruptedException {
        Object lock = new Object();
        final int[] data = {0};  // 共享数据

        // 消费者线程
        Thread consumer = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("[消费者] 等待数据...");
                    lock.wait();  // 等待，释放锁
                    System.out.println("[消费者] 收到数据: " + data[0]);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Consumer");

        // 生产者线程
        Thread producer = new Thread(() -> {
            try {
                Thread.sleep(1000);  // 模拟生产数据的耗时
                synchronized (lock) {
                    data[0] = 42;
                    System.out.println("[生产者] 生产数据: " + data[0]);
                    lock.notify();  // 唤醒一个等待的线程
                    System.out.println("[生产者] 已通知消费者");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "Producer");

        consumer.start();
        producer.start();
        consumer.join();
        producer.join();
    }

    /**
     * 示例2：notifyAll() 演示
     * 演示唤醒所有等待线程
     */
    static void example2_NotifyAll() throws InterruptedException {
        Object lock = new Object();

        // 创建3个消费者线程
        Thread consumer1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("[消费者1] 开始等待...");
                    lock.wait();
                    System.out.println("[消费者1] 被唤醒了！");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Consumer-1");

        Thread consumer2 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("[消费者2] 开始等待...");
                    lock.wait();
                    System.out.println("[消费者2] 被唤醒了！");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Consumer-2");

        Thread consumer3 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("[消费者3] 开始等待...");
                    lock.wait();
                    System.out.println("[消费者3] 被唤醒了！");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Consumer-3");

        // 生产者线程
        Thread producer = new Thread(() -> {
            try {
                Thread.sleep(1000);
                synchronized (lock) {
                    System.out.println("[生产者] 调用 notifyAll() 唤醒所有等待线程");
                    lock.notifyAll();  // 唤醒所有等待的线程
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "Producer");

        consumer1.start();
        consumer2.start();
        consumer3.start();
        producer.start();

        consumer1.join();
        consumer2.join();
        consumer3.join();
        producer.join();
    }

    /**
     * 示例3：wait(timeout) 演示
     * 演示带超时的等待
     */
    static void example3_WaitWithTimeout() throws InterruptedException {
        Object lock = new Object();

        Thread waiter = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("[等待线程] 开始等待，超时时间为 2000ms");
                    long startTime = System.currentTimeMillis();
                    lock.wait(2000);  // 等待2秒，如果没有被唤醒就自动返回
                    long endTime = System.currentTimeMillis();
                    System.out.println("[等待线程] 等待结束，实际等待时间: " + (endTime - startTime) + "ms");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Waiter");

        waiter.start();
        waiter.join();

        System.out.println("\n[说明] 由于没有调用 notify()，线程等待了 2000ms 后自动返回");
    }
}
